/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package network;

import controllers.DatabaseController;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Collection;
import java.util.Iterator;
import util.CompleteFile;

/**
 *
 * @author gravena
 */
public class ListRequestHandler implements Runnable {

    private Socket conn;
    private final DatabaseController dbController;

    public ListRequestHandler(DatabaseController dbController, Socket conn) {
        this.dbController = dbController;
        this.conn = conn;
    }

    @Override
    public void run() {
        try {
            DataOutputStream output = new DataOutputStream(this.conn.getOutputStream());
            output.write(this.makePacket());
            output.close();
            conn.close();
        } catch (IOException ex) {
            System.err.println("Erro ao estabelecer canal de comunicação!\n" + ex.getMessage());
        }
    }

    public byte[] makePacket() {
        /* Estruturas usadas para montar o pacote */
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        DataOutputStream dos = new DataOutputStream(bos);

        //synchronized (dbController.getRemoteListLock()) {
        int totalPacketSize = 0;
        synchronized (this.dbController) {
            try {
                int numberOfLocalFiles;
                long localVersion;
                byte[] localUUIDString;
                
                numberOfLocalFiles = this.dbController.getNumberOfLocalFiles();
                localVersion = this.dbController.getLocalVersion();
                localUUIDString = this.dbController.getLocalUUIDString().getBytes();

                byte records[][] = new byte[numberOfLocalFiles][];

                Iterator<CompleteFile> it = this.dbController.getLocalFileCollection().iterator();
                for (int i = 0; i < numberOfLocalFiles; i++) {
                    bos.reset();
                    CompleteFile file = it.next();
                    dos.write(file.getHashMD5());
                    dos.writeLong(file.getSize());
                    int nameSize = file.getName().length();
                    dos.writeInt(nameSize);
                    dos.write(file.getName().getBytes());
                    dos.writeBoolean(file.isComplete());

                    dos.flush();

                    records[i] = bos.toByteArray();
                    totalPacketSize += records[i].length;
                }


                /*
                 * UUID - 32 bytes (String(32))
                 * Version 8 bytes (long) | Packet Size 4 bytes (int)
                 */
                byte[] packet = new byte[44 + totalPacketSize];
                bos.reset();
                dos.write(localUUIDString);
                dos.writeLong(localVersion);
                dos.writeInt(totalPacketSize);

                /* Copiando o cabeçalho para o pacote final */
                System.arraycopy(bos.toByteArray(), 0, packet, 0, 44);
                int offset = 0;
                for (int i = 0; i < numberOfLocalFiles; i++) {
                    System.arraycopy(records[i], 0, packet, 44 + (offset), records[i].length);
                    offset += records[i].length;
                }

                return packet;

            } catch (IOException ex) {
                System.err.println("Erro na montagem do Header\n" + ex.getMessage());
                return null;
            }
        }

        //}
    }
}
